package com.bestcem.xm.user.util.business;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.enums.AuthErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.componet.filestorage.service.StorageService;
import com.bestcem.xm.user.config.properties.MailSubjectNotifyTitleEnumProperties;
import com.bestcem.xm.user.config.properties.SettingProperties;
import com.bestcem.xm.user.config.properties.SingleOrgProperties;
import com.bestcem.xm.user.constant.UserCacheKeyConstant;
import com.bestcem.xm.user.entity.pojo.UserDO;
import com.bestcem.xm.user.enums.*;
import com.bestcem.xm.user.grpc.client.IndustryGrpcService;
import com.bestcem.xm.user.service.MailService;
import com.bestcem.xm.user.service.OrganizationCustomSettingService;
import com.bestcem.xm.user.service.OrganizationService;
import com.bestcem.xm.user.service.UserService;
import com.bestcem.xm.user.service.dto.order.RecordToOmDTO;
import com.bestcem.xm.user.service.dto.user.*;
import com.bestcem.xm.user.service.third.OaService;
import com.bestcem.xm.user.service.third.PhoneService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 用户相关工具类
 *
 * @author qiongyu.cui <qiongyu.cui@idiaoyan.com>
 * @version v1.0
 * @date 2022/3/9 10:50
 */
@Component
@Slf4j
public class UserUtil {

    @Resource
    private SingleOrgProperties singleOrgProperties;

    @Resource
    private UserCacheUtil userCacheUtil;

    @Resource
    private OrganizationCustomSettingService organizationCustomSettingService;

    @Resource
    private OrganizationService organizationService;

    @Resource
    private SettingProperties settingProperties;

    @Resource
    private MailSubjectNotifyTitleEnumProperties mailSubjectNotifyTitleEnumProperties;

    @Resource
    private PhoneService phoneService;

    @Resource
    private MailService mailService;

    //@Resource
    //private UserMessageSender userMessageSender;

    @Resource
    private OaService oaService;

    @Resource
    private UserService userService;

    /*@Resource
    private OssService ossService;*/

    @Autowired
    private StorageService storageService;

    @Resource
    private IndustryGrpcService industryGrpcService;

    /**
     * 获取指定公司的域名
     * python引用：apps_mysql.utils.get_corp_url
     *
     * @param orgId           租户id
     * @param orgCode         租户code
     * @param requestHost     请求host
     * @param requestProtocol 请求协议
     * @return java.lang.String 公司域名
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/05/10 14:10
     */
    public String getCorpUrl(String orgId, String orgCode, String requestHost, String requestProtocol) {
        if (StringUtils.isNotBlank(singleOrgProperties.getRealUrl())) {
            return singleOrgProperties.getRealUrl();
        }

        StringBuilder stb = new StringBuilder();
        if (StringUtils.isNotBlank(orgCode)) {
            stb.append(settingProperties.getServerProtocol()).append("://").append(orgCode).append(".").append(settingProperties.getXmServerHost());
            if (StringUtils.isBlank(orgId)) {
                return stb.toString();
            }
            // 根据org_id、enable查询租户自定义配置信息
            ServiceResult<OrganizationCustomSettingDTO> settingResult = organizationCustomSettingService.selectByOrgIdAndEnable(orgId, true);
            String domain = "";
            if (settingResult.isSuccess() && Objects.nonNull(settingResult.getData())) {
                domain = settingResult.getData().getDomain();
            }
            if (StringUtils.isNotBlank(domain)) {
                stb = new StringBuilder();
                return stb.append(settingProperties.getServerProtocol()).append("://").append(domain).toString();
            }
            return stb.toString();
        }
        stb.append(StringUtils.isNotBlank(requestProtocol) ? requestProtocol : settingProperties.getServerProtocol()).append("://");
        stb.append(StringUtils.isNotBlank(requestHost) ? requestHost : settingProperties.getXmServerHost());
        return stb.toString();
    }

    /**
     * 根据orgId获取域名
     *
     * @param orgId
     * @return java.lang.String
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/6/19 20:11
     */
    public String getOrgCustomSetting(String orgId) {
        if (StringUtils.isBlank(orgId)) {
            return "";
        }
        // 根据org_id、enable查询租户自定义配置信息
        ServiceResult<OrganizationCustomSettingDTO> settingResult = organizationCustomSettingService.selectByOrgIdAndEnable(orgId, true);
        String domain = "";
        if (settingResult.isSuccess() && Objects.nonNull(settingResult.getData())) {
            domain = settingResult.getData().getDomain();
        }
        return domain;
    }

    /**
     * 获取指定公司的域名
     * python引用：web.handlers.BaseHandler.get_corp_code
     *
     * @param orgCode 公司code
     * @return java.lang.String
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/03/29 11:08
     */
    public String getCorpUrl(String orgCode) {
        return getCorpUrl("", orgCode, "", "");
    }

    /**
     * 获取指定公司的orgCode
     * python引用：web.handlers.BaseHandler.get_corp_code
     *
     * @param requestHost 请求的host
     * @return java.lang.String 公司的code
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/05/10 14:12
     */
    public ServiceResult<String> getCorpCode(String requestHost) {
        if (StringUtils.isNotBlank(requestHost) && requestHost.contains(settingProperties.getXmServerHost())) {
            return ServiceResult.success(requestHost.split("\\.")[0]);
        }

        // 根据domain和enable查询租户自定义配置信息
        ServiceResult<OrganizationCustomSettingDTO> settingResult = organizationCustomSettingService.selectBydomainAndEnable(requestHost, true);
        if (settingResult.isSuccess() && Objects.nonNull(settingResult.getData())) {
            OrganizationCustomSettingDTO data = settingResult.getData();
            String orgId = data.getOrgId();
            // 根据orgId查询租户信息
            ServiceResult<OrganizationDTO> organization = organizationService.selectByPrimaryKey(orgId);
            if (organization.isSuccess() && Objects.nonNull(organization.getData())) {
                // 组装自定义域名相关信息，并存到到线程的本地变量
                OrgCustomSettingInfoDTO settingInfoDTO = new OrgCustomSettingInfoDTO();
                settingInfoDTO.setOrgCode(organization.getData().getCode());
                settingInfoDTO.setDomain(data.getDomain());
                settingInfoDTO.setFavicon(data.getFavicon());
                CustomSettingThreadLocalUtil.setCustomSetting(settingInfoDTO);
                return ServiceResult.success(organization.getData().getCode());
            }
        }
        return ServiceResult.fail(AuthErrorCodeEnum.ORG_NOT_EXISTS, "organization not exist");
    }

    /**
     * 获取指定公司的orgCode
     * python引用：web.handlers.BaseHandler.get_corp_code
     *
     * @param orgCode    公司code
     * @param serverName 请求的服务名称
     * @return com.bestcem.xm.util.ServiceResult<java.lang.String>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/03/29 11:06
     */
    public ServiceResult<String> getCorpCode(String orgCode, String serverName) {
        if (StringUtils.isNotBlank(singleOrgProperties.getCode())) {
            return ServiceResult.success(singleOrgProperties.getCode());
        }
        if (StringUtils.isNotBlank(orgCode)) {
            return ServiceResult.success(orgCode);
        }

        return getCorpCode(serverName);
    }

    /**
     * 邮件通知销售
     * python引用：apps_mysql.user.util.utils.notify_sales
     *
     * @param notifySalesInfo 通知内容
     * @return void
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/06/06 16:42
     */
    public void notifySales(NotifySalesDTO notifySalesInfo) {
        // 无需发送销售邮件通知的
        if (Objects.isNull(notifySalesInfo.getUserInfo())) {
            return;
        }
        UserDTO userInfo = notifySalesInfo.getUserInfo();
        if (BooleanStatusEnum.YES.getStatus().equals(notifySalesInfo.getOrgNotifySalesFlag())) {
            return;
        }
        if (BooleanStatusEnum.YES.getStatus().equals(userInfo.getInnerFlag())) {
            return;
        }

        // 获取销售的邮件列表
        List<String> salesEmailList = industryGrpcService.getIndustrySalesEmails();
        if (log.isInfoEnabled()) {
            log.info("[USER] userUtil notifySales ip:{} ", salesEmailList);
        }
        // 获取手机号码归属地
        String phoneLocation = phoneService.getPhoneLocation(userInfo.getPhone());
        String content = StringUtils.isBlank(notifySalesInfo.getContent()) ? getEmailContent(userInfo) : notifySalesInfo.getContent();

        // 根据邮箱发送应用邮件通知
        NotifyApplicationByEmailDTO emailDTO = new NotifyApplicationByEmailDTO();
        emailDTO.setOrgId(notifySalesInfo.getOrgId());
        emailDTO.setToEmail(salesEmailList);
        emailDTO.setUsername(userInfo.getName());
        emailDTO.setCompanyName(notifySalesInfo.getOrgName());
        emailDTO.setCompanyType(notifySalesInfo.getIndustryName());
        emailDTO.setEmail(userInfo.getEmail());
        emailDTO.setPhone(userInfo.getPhone());
        emailDTO.setContent(content);
        emailDTO.setSubject(String.format("[%s申请信息-免费版]", settingProperties.getXmName()));
        emailDTO.setLoc(phoneLocation);
        emailDTO.setSource(notifySalesInfo.getSource());
        emailDTO.setScenarioDTO(notifySalesInfo.getScenarioDTO());
        notifyApplicationByEmail(emailDTO);

        // 更新租户销售通知标识为true
        OrganizationDTO updateParam = new OrganizationDTO();
        updateParam.setOrgId(notifySalesInfo.getOrgId());
        updateParam.setNotifySalesFlag(BooleanStatusEnum.YES.getStatus());
        updateParam.setLocation(phoneLocation);
        updateParam.setSeoSource(notifySalesInfo.getSource());
        organizationService.updateByPrimaryKeySelective(updateParam);
    }

    /**
     * 根据邮箱发送应用邮件通知
     * apps_mysql.common.utils.notify_application_by_email
     *
     * @param emailDTO 发送内容对象
     * @return void
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/06/06 19:10
     */
    public void notifyApplicationByEmail(NotifyApplicationByEmailDTO emailDTO) {
        if (Objects.isNull(emailDTO)) {
            return;
        }
        if (StringUtils.isBlank(emailDTO.getSubject())) {
            emailDTO.setSubject(String.format("[%s申请信息-免费版]", settingProperties.getXmName()));
        }

        // 组装邮件参数信息
        HashMap<String, Object> emailContentParam = new HashMap<>();
        emailContentParam.put("username", emailDTO.getUsername());
        emailContentParam.put("company_name", emailDTO.getCompanyName());
        emailContentParam.put("company_type", emailDTO.getCompanyType());
        emailContentParam.put("email", emailDTO.getEmail());
        emailContentParam.put("phone", emailDTO.getPhone());
        emailContentParam.put("content", emailDTO.getContent());
        emailContentParam.put("time", DateUtil.convertDteToString(new Date(), DateUtil.YYYY_MM_DD));
        emailContentParam.put("loc", emailDTO.getLoc());
        emailContentParam.put("source", emailDTO.getSource());
        String scenarioTitle = (Objects.nonNull(emailDTO.getScenarioDTO()) && StringUtils.isNotEmpty(emailDTO.getScenarioDTO().getTitle()))
                ? emailDTO.getScenarioDTO().getTitle() : "";
        emailContentParam.put("scenario_title", scenarioTitle);

        // 发送邮件
        List<String> toEmails = emailDTO.getToEmail();
        log.info("[USER]邮件同步notifyApplicationByEmail，toEmails={}", emailDTO.getToEmail().toString());
        boolean sendEmailResult = mailService.sendEmail(toEmails.toArray(new String[toEmails.size()]), emailDTO.getSubject(),
                EmailTemplateEnum.APPLICATION_EMAIL_TEMPLATE.getFileName(), emailContentParam);
        String content = StringFormatUtil.templateFormat(EmailTemplateEnum.APPLICATION_EMAIL_TEMPLATE.getFileName(), emailContentParam);
        // 同步消息到系统商后台
        Integer notifyStatus = sendEmailResult ? NotifyStatusEnum.IS_SEND.getType() : NotifyStatusEnum.SEND_FAILED.getType();
        if (mailSubjectNotifyTitleEnumProperties.containsSubject(emailDTO.getSubject())) {
            String title = mailSubjectNotifyTitleEnumProperties.getTitle(emailDTO.getSubject());
            RecordToOmDTO recordToOmDTO = new RecordToOmDTO();
            recordToOmDTO.setContent(content);
            recordToOmDTO.setName(title);
            recordToOmDTO.setOrgId(StringUtils.isNotBlank(emailDTO.getOrgId()) ? emailDTO.getOrgId() : "");
            recordToOmDTO.setReceiver(String.join(",", emailDTO.getToEmail()));
            recordToOmDTO.setSender("倍市得");
            recordToOmDTO.setType(NotifyTypeEnum.EMAIL.getType());
            recordToOmDTO.setStatus(notifyStatus);
            recordToOmDTO.setSendTime(DateUtil.convertDteToString(new Date(), DateUtil.NORM_DATETIME_PATTERN));
            recordToOmDTO.setTemplateId("");
            recordToOmDTO.setParams(JSON.toJSONString(emailContentParam));
            recordToOm(recordToOmDTO);
        }
    }

    /**
     * 获取 给销售发送邮件的content
     *
     * @param userInfo 用户信息
     * @return java.lang.String 内容
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/06/06 16:28
     */
    public String getEmailContent(UserDTO userInfo) {
        if (Objects.nonNull(userInfo) && StringUtils.isNotBlank(userInfo.getPhone())) {
            if (StringUtils.isNotBlank(userInfo.getWxOffiOpenid())) {
                return EmailContentEnum.WECHAT_REGISTER.getDesc();
            }
            if (StringUtils.isNotBlank(userInfo.getPassword())) {
                return EmailContentEnum.MOBILE_REGISTER.getDesc();
            }
            return EmailContentEnum.FAST_REGISTER.getDesc();
        }
        return "空";
    }

    /**
     * 同步消息到系统商后台
     * python引用：apps_mysql/common/utils.py:56
     *
     * @param recordToOmDTO 消息内容
     * @return void
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/06/07 09:33
     */
    public void recordToOm(RecordToOmDTO recordToOmDTO) {
        // 消息同步至 系统商后台通知中心
        if (BooleanStatusEnum.YES.getBoolValue().equals(settingProperties.getBaselineFlag())) {
            return;
        }
        if (log.isInfoEnabled()) {
            log.info(String.format("MQ:notify_java---------------------name:%s", recordToOmDTO.getName()));
        }
        RecordToOmDTO recordDTO = new RecordToOmDTO();
        recordDTO.setContent(recordToOmDTO.getContent());
        recordDTO.setName(StringUtils.isNotBlank(recordToOmDTO.getName()) ? recordToOmDTO.getName() : "");
        recordDTO.setOrgId(StringUtils.isNotBlank(recordToOmDTO.getOrgId()) ? recordToOmDTO.getOrgId() : "");
        recordDTO.setReceiver(StringUtils.isNotBlank(recordToOmDTO.getReceiver()) ? recordToOmDTO.getReceiver() : "");
        recordDTO.setSender(StringUtils.isNotBlank(recordToOmDTO.getSender()) ? recordToOmDTO.getSender() : "");
        recordDTO.setType(recordToOmDTO.getType() != null ? recordToOmDTO.getType() : NotifyTypeEnum.MOBILE.getType());
        recordDTO.setStatus(recordToOmDTO.getStatus() != null ? recordToOmDTO.getStatus() : NotifyStatusEnum.IS_SEND.getType());
        recordDTO.setSendTime(StringUtils.isNotBlank(recordToOmDTO.getSendTime()) ? recordToOmDTO.getSendTime() : DateUtil.convertDteToString(new Date(), DateUtil.NORM_DATETIME_PATTERN));
        recordDTO.setTemplateId(StringUtils.isNotBlank(recordToOmDTO.getTemplateId()) ? recordToOmDTO.getTemplateId() : "");
        recordDTO.setParams(StringUtils.isNotBlank(recordToOmDTO.getParams()) ? recordToOmDTO.getParams() : "");
        if (Objects.nonNull(recordToOmDTO.getSmsChannel())) {
            recordDTO.setSmsChannel((recordToOmDTO.getSmsChannel()));
        }
        //userMessageSender.recordToOm(recordToOmDTO);
    }

    /**
     * 判断是否为内部用户
     * True 是内部员工， False 非内部员工
     *
     * @param mobile  手机号
     * @param email   邮箱
     * @param orgName 租户名称
     * @return java.lang.Boolean
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/06/16 16:56
     */
    public boolean checkUserIsInner(String mobile, String email, String orgName) {
        boolean result = false;
        if (!BooleanStatusEnum.YES.getBoolValue().equals(settingProperties.getIsXm())) {
            return true;
        }
        if (StringUtils.isNotEmpty(mobile)) {
            // 调用oahelper接口
            ServiceResult<Boolean> checkMobile = oaService.checkMobile(mobile);
            if (BooleanStatusEnum.YES.getBoolValue().equals(checkMobile.getData())) {
                return true;
            }
        }
        // 是否满足内部员工邮箱格式
        if (StringUtils.isNotBlank(email) && (email.endsWith("@wenjuan.com") || email.endsWith("@idiaoyan.com"))) {
            return true;
        }
        // 获取配置文件中内部员工信息
        Map<String, JSONArray> innerMap = FileUtils.readInnerUserFile(FileUtils.INNER_USER_FILE_PATH);
        // 手机号和邮箱是否满足
        if (innerMap.get("INNER_EMAIL").contains(email) || innerMap.get("INNER_MOBILE").contains(mobile)) {
            return true;
        }
        // 名称是否满足
        if (StringUtils.isNotEmpty(orgName) && innerMap.get("INNER_NAME").contains(orgName)) {
            return true;
        }

        return result;
    }

    /**
     * 给指定email的用户发送重置密码邮件
     *
     * @param orgCode           公司code
     * @param requestServerName 请求的服务名
     * @param requestProtocol   请求的协议
     * @param email             邮箱
     * @param uri               urldizhi
     * @return com.bestcem.xm.util.ServiceResult<java.lang.Void>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/06/19 13:21
     */
    public ServiceResult<Void> sendResetPwdEmail(String orgCode, String requestServerName, String requestProtocol, String email, String uri) {
        ServiceResult<String> corpCode = getCorpCode(orgCode, requestServerName);
        if (!corpCode.isSuccess()) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未查询到当前的租户code");
        }
        orgCode = corpCode.getData();

        // 根据orgCode查询org信息
        ServiceResult<OrganizationDTO> organizationResult = organizationService.selectByOrgCode(orgCode);
        OrganizationDTO organization = organizationResult.getData();
        if (ObjectUtil.isEmpty(organization)) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未查询到当前的租户信息");
        }

        // 根据orgId和email查询用户信息
        UserDTO userParam = new UserDTO();
        userParam.setOrgId(organization.getOrgId());
        userParam.setEmail(email);
        userParam.setStatus(UserStatusEnum.INACTIVATED.getStatus());
        ServiceResult<List<UserDO>> usersResult = userService.selectByOrgIdSelective(userParam);
        if (!usersResult.isSuccess() || CollectionUtils.isEmpty(usersResult.getData())) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "user not found");
        }

        UserDO userDO = usersResult.getData().get(0);
        String userId = userDO.getUserId();
        // 获取重置密码的缓存
        String cacheKey = userCacheUtil.buildKey(UserCacheKeyConstant.RESET_PASSWORD_TOKEN_KEY, userId);
        String activateToken = userCacheUtil.get(cacheKey, String.class);
        if (StringUtils.isEmpty(activateToken)) {
            activateToken = UUID.randomUUID().toString();
        }
        userCacheUtil.setEx(cacheKey, activateToken, 2, TimeUnit.HOURS);

        try {
            // 考虑重置密码的时候host是www.xxx的情况
            if (StringUtils.isNotEmpty(orgCode) && requestServerName.startsWith("www.")) {
                requestServerName = orgCode + requestServerName.substring(3);
            }

            String activateUrl = requestProtocol + "://" + requestServerName + uri + "?uid=" + userId + "&token=" + activateToken;
            HashMap<String, Object> paramMap = new HashMap<>();
            paramMap.put("name", userDO.getName());
            paramMap.put("hours", 2);
            paramMap.put("activate_url", activateUrl);
            paramMap.put("today", DateUtil.convertDteToString(new Date(), "yyyy年MM月dd日"));
            //paramMap.put("oss_url_prefix", ossService.getUrlPrefix());
            paramMap.put("oss_url_prefix", storageService.getPropertiesValueBy(null, "domain") + storageService.getPropertiesValueBy(null, "base-path"));

            String subject = settingProperties.getBestcemEmailSign() + "重置密码";
            boolean sendEmailResult = mailService.sendEmail(new String[]{email}, subject,
                    EmailTemplateEnum.RESET_PWD_TEMPLATE.getFileName(), paramMap);
            String content = StringFormatUtil.templateFormat(EmailTemplateEnum.RESET_PWD_TEMPLATE.getFileName(), paramMap);
            // 同步消息到系统商后台
            Integer notifyStatus = sendEmailResult ? NotifyStatusEnum.IS_SEND.getType() : NotifyStatusEnum.SEND_FAILED.getType();
            if (mailSubjectNotifyTitleEnumProperties.containsSubject(subject)) {
                String title = mailSubjectNotifyTitleEnumProperties.getTitle(subject);
                RecordToOmDTO recordToOmDTO = new RecordToOmDTO();
                recordToOmDTO.setContent(content);
                recordToOmDTO.setName(title);
                recordToOmDTO.setOrgId(organization.getOrgId());
                recordToOmDTO.setReceiver(email);
                recordToOmDTO.setSender("倍市得");
                recordToOmDTO.setType(NotifyTypeEnum.EMAIL.getType());
                recordToOmDTO.setStatus(notifyStatus);
                recordToOmDTO.setSendTime(DateUtil.convertDteToString(new Date(), DateUtil.NORM_DATETIME_PATTERN));
                recordToOmDTO.setTemplateId("");
                recordToOmDTO.setParams("");
                recordToOm(recordToOmDTO);
            }
        } catch (Exception e) {
            log.error("给指定email的用户发送重置密码邮件异常：{}", e);
            userCacheUtil.delete(cacheKey);
        }

        return ServiceResult.success();
    }

}
